package com.kitty.mina.filter;


import com.kitty.common.utils.SpringUtils;
import com.kitty.mina.FireWallConfig;
import com.kitty.mina.FloodRecord;
import com.kitty.mina.session.SessionManager;
import com.kitty.mina.session.SessionProperties;
import com.kitty.game.utils.NumberUtil;
import com.kitty.game.utils.TimeUtil;
import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//后加



public class FloodFilter extends IoFilterAdapter {


    @Override
    public void messageReceived(NextFilter nextFilter, IoSession session, Object message)
            throws Exception {
        FloodRecord record = getFloodRecordBy(session);

        // 基础思路：玩家XX秒内累计洪水记录超过Y次，则判定为嫌疑人
        long now = System.currentTimeMillis();
        long currSecond = NumberUtil.intValue(now / TimeUtil.ONE_SECOND);
        long lastTime = record.getLastReceivedTime();
        int lastSecond = NumberUtil.intValue(lastTime / TimeUtil.ONE_SECOND);

        tryToResetFloodTimes(now, record);

        if (currSecond == lastSecond) {
            int packageSum = record.addSecondReceivedPackage();
            if (isMessageTooFast(packageSum)) {
                int floodTimes = record.addFloodTimes();
                if (isMeetFloodStandard(floodTimes)) {
//                    logger.info("session窗口期洪水记录超过上限");
                    // TODO 注销session
                }
                record.setLastFloodTime(now);
                // 已经检查到洪水，则需要重置收包次数
                record.setReceivedPacksLastSecond(0);
            }
        } else {
            record.setReceivedPacksLastSecond(0);
        }

        record.setLastReceivedTime(now);

        nextFilter.messageReceived(session, message);
    }

    private static FloodRecord getFloodRecordBy(IoSession session) {
        SessionManager sessionMgr = SessionManager.INSTANCE;
        FloodRecord record = sessionMgr.getSessionAttr(session,
                SessionProperties.FLOOD, FloodRecord.class);
        if (record == null) {
            record = new FloodRecord();
            session.setAttribute(SessionProperties.FLOOD, record);
        }

        return record;
    }

    private static void tryToResetFloodTimes(long now, FloodRecord record) {
        FireWallConfig config = SpringUtils.getBean(FireWallConfig.class);
        long diffTime = now - record.getLastFloodTime();
        if (NumberUtil.intValue(diffTime / TimeUtil.ONE_SECOND) > config.getFloodWindowSeconds()) {
            record.setFloodTimes(0);
        }
    }

    private static boolean isMessageTooFast(int packageSum) {
        FireWallConfig config = SpringUtils.getBean(FireWallConfig.class);
        return packageSum >= config.getMaxPackagePerSecond();
    }

    private static boolean isMeetFloodStandard(int floodTimes) {
        FireWallConfig config = SpringUtils.getBean(FireWallConfig.class);
        return floodTimes > config.getMaxFloodTimes();
    }

}
